function ace() {
    if ($('#cause-effect').is(':checked')) {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
    else {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
}
function up_down() {
    if ($('#hy-per').is(':checked')) {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
    else {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
}
function cta() {
    if ($('#concrete-to-abstract').is(':checked')) {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
    else {
        var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
        var nodes = result[0];
        var links = result[1];

        var option = myChart.getOption();
        option.series[0].nodes = nodes;
        option.series[0].links = links;
        myChart.setOption(option);
    }
}
// 节点样式
var NODE_STYLE_DICT = {
    // 抽象事件
    'abstract': {
        itemStyle: {
            normal: {
                color: '#4990E2'
            }
        },
        label: {
            normal: {
                color: '#FFFFFF'
            }
        }
    },
    // 具体事件
    'concrete': {
        itemStyle: {
            normal: {
                color: '#B99C9E'
            }
        },
        label: {
            normal: {
                color: '#FFF'
            }
        }
    },
    // 高亮（点击过）的事件
    'highlight': {
        itemStyle: {
            normal: {
                color: '#E47473'
            }
        },
        label: {
            normal: {
                color: '#FFF'
            }
        }
    },
    'independent': {
        itemStyle: {
            normal: {
                color: '#ADE7BC'
            }
        },
        label: {
            normal: {
                color: '#FFF'
            }
        }
    }
};

// 边样式
var LINK_STYLE_DICT = {
    // 抽象因果边
    'abstract_cause_effect': {
        symbol: ['none', 'arrow'],
        symbolSize: [1, 15],
        lineStyle: {
            normal: {
                color: '#4990E2'
            }
        }
    },
    // 具体到抽象边
    'concrete_to_abstract': {
        symbol: ['arrow', 'arrow'],
        symbolSize: [15, 1],
        lineStyle: {
            normal: {
                color: '#C0C1C2',
                type: "dashed"
            }
        }
    },
    // 上下位边
    'hyper': {
        symbol: ['arrow', 'none'],
        symbolSize: [15, 1],
        lineStyle: {
            normal: {
                color: '#ADE7BC'
            }
        }
    },
    'opacity': {
        lineStyle: {
            normal: {
                opacity: 0
            }
        }
    }
};

// 记录已获取的事件
var EVENT_DICT = {};
// 记录已获取的关系
var RELATION_DICT = {};
// 图表对象
var myChart = null;

// 由事件和关系构建节点和边
function buildNodesAndLinks(eventMap, relationMap) {
    var nodes = [];
    var links = [];

    Object.values(eventMap).forEach(function (event) {
        var node = {};
        node.name = event['code'];
        node.value = event['text'];
        node.category = event['category'];
        nodes.push($.extend(node, NODE_STYLE_DICT[event['category']]));
    });
    Object.values(relationMap).forEach(function (relation) {
        var link = {};
        link.source = relation['head'];
        link.target = relation['tail'];
        link.category = relation['category'];
        if (relation['category'] === 'abstract_cause_effect') {
            link.exampleCause = relation['example_cause'];
            link.exampleEffect = relation['example_effect'];
            link.exampleCondition = relation['example_condition'];
            link.exampleConcurrent = relation['example_concurrent'];
            link.exampleComposition = relation['example_composition'];
            link.exampleShortContext = relation['example_short_context'];
            link.exampleLongContext = relation['example_long_context'];
            link.weight = relation['confidence'];
            var isShow = $('#cause-effect').is(':checked');
            if (isShow) {
                links.push($.extend(link, LINK_STYLE_DICT[relation['category']]));
            }
            else {

            }
        }
        if (relation['category'] === 'concrete_to_abstract') {
            if ($('#concrete-to-abstract').is(':checked')) {
                links.push($.extend(link, LINK_STYLE_DICT[relation['category']]));
            }
            else {
                for (let node in nodes) {
                    if ((nodes[node].name == link.source) && (nodes[node].category = 'concrete')) {
                        nodes.splice(node, 1);
                        break;
                    }
                }
                for (let linkk in links) {
                    var degree = 0;
                    if (!$('#hy-per').is(':checked')) {
                        for (let nodee in nodes) {
                            if (links[linkk].source == nodes[nodee].name) {
                                degree++;
                            }
                        }
                        if (degree == 0) {
                            links.splice(linkk, 1);
                        }
                    }
                }
            }
        }
        if (relation['category'] === 'hyper') {
            var isShow = $('#hy-per').is(':checked');
            if (isShow) {
                links.push($.extend(link, LINK_STYLE_DICT[relation['category']]));
            }
            else {
            }
        }

    });

    //删除多余的边
    for (var i = 0; i < nodes.length; i++) {
        for (let link in links) {
            var noneline = 0;
            for (let node in nodes) {
                if (links[link].source == nodes[node].name) {
                    noneline++;
                }
            }
            if (noneline == 0) {
                links.splice(link, 1);
                break;
            }
        }
        for (let link in links) {
            var noneline = 0;
            for (let node in nodes) {
                if (links[link].target == nodes[node].name) {
                    noneline++;
                }
            }
            if (noneline == 0) {
                links.splice(link, 1);
                break;
            }
        }
    }

    //剔除独立节点
    for (var i = 0; i < 5; i++) {
        for (let node in nodes) {
            var degree = 0;
            for (let link in links) {
                if (links[link].source == nodes[node].name) {
                    if (nodes.indexOf(links[link].target)) {
                        degree++;
                    }
                }
                else if (links[link].target == nodes[node].name) {
                    if (nodes.indexOf(links[link].source)) {
                        degree++;
                    }
                }
            }
            if (degree < 1) {
                nodes.splice(node, 1);
            }
        }
    }

    //反向去事件泛化边
    for (let link in links) {
        var tmp = 0;
        if (links[link].category == 'concrete_to_abstract') {
            tmp = links[link].target;
            links[link].target = links[link].source;
            links[link].source = tmp;
        }
    }

    //筛选abstract节点
    for (let node in nodes) {
        if (nodes[node].category == 'abstract') {
            var count = 0;
            for (let link in links) {
                if (links[link].category == 'abstract_cause_effect') {
                    if (links[link].source == nodes[node].name) {
                        count++;
                        break;
                    }
                    if (links[link].target == nodes[node].name) {
                        count++;
                        break;
                    }
                }
            }
            if (count <= 0) {
                nodes[node].itemStyle = {
                    normal: {
                        color: '#ADE7BC'
                    }
                };
                nodes[node].category = 'independent';
                nodes[node].label = {
                    normal: {
                        color: '#111'
                    }
                }
            }
        }
    }
    return [nodes, links];
}
// 初始化图谱
function initGraph() {
    // 基于准备好的dom，初始化echarts实例
    myChart = echarts.init(document.getElementById('main'));
    var option = {
        // 不播放动画
        animation: false,
        // 鼠标放到节点和边上时的提示
        tooltip: {
            // 文本显示方式
            formatter: function (param) {
                var dataType = param.dataType;
                if (dataType === 'node') {
                    var node = param.data;
                    return '<span style="color:' + param.color + ';">●</span> ' + node.value;
                } else if (dataType === 'edge') {
                    var link = param.data;
                    var head = EVENT_DICT[link.source];
                    var tail = EVENT_DICT[link.target];
                    return head.text + ' > ' + tail.text;
                }
            }
        },
        // 数据列
        series: [
            {
                // 图表类型
                type: 'graph',
                // 初始缩放
                zoom: 0.6,
                // 节点大小
                symbolSize: 90,
                // 开启滚轮缩放和平移漫游
                roam: true,
                // 布局方式
                layout: 'force',
                // 允许拖动单个节点
                draggable: true,
                // 鼠标放到节点上时，高亮显示该节点及相邻节点
                focusNodeAdjacency: true,
                // 力导向图配置
                force: {
                    //节点之间的斥力因子。支持数组表达斥力范围，值越大斥力越大。
                    // repulsion: [4000, 6000],
                    repulsion: [8000, 10000],
                    //节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
                    gravity: 0.4,
                    //边的两个节点之间的距离，这个距离也会受 repulsion。[10, 50] 。值越小则长度越长
                    // edgeLength: [20, 50],
                    edgeLength: [30, 40],
                    // 不显示力导向图变为平衡状态的动画（拖动节点时显示动画效果更好）
                    // layoutAnimation: false
                },
                // 节点上的标签
                label: {
                    normal: {
                        // 一直显示
                        show: true,
                        // 标签颜色
                        // color: '#FFF',
                        // 字号
                        fontSize: 12,
                        // 位置
                        position: 'inside',
                        // 文本显示方式
                        formatter: function (param) {
                            var node = param.data;
                            var title = node.value;
                            if (title.length < 3) {
                                return title;
                            }
                            var str = '';
                            str += title.substring(0, 3);
                            str += "\n";
                            str += title.substring(3, Math.min(7, title.length));
                            if (title.length > 6) {
                                str += "\n";
                                str += title.substring(7, Math.min(10, title.length));
                                if (title.length > 10) {
                                    str += "...";
                                }
                            }
                            return str;
                        }
                    }

                },
                // 边上的标签
                edgeLabel: {
                    normal: {
                        // 一直显示
                        show: true,
                        // 文本样式
                        textStyle: {
                            fontSize: 10
                        },
                        // 文本显示方式
                        formatter: function (param) {
                            var link = param.data;
                            var result = '';
                            if (link.weight !== undefined) {
                                result = link.weight.toFixed(2);
                            }
                            return result;
                        }
                    }
                },
                // 通用节点样式
                itemStyle: {
                    normal: {
                        // 阴影效果
                        shadowColor: 'rgba(0, 0, 0, 0.5)',
                        shadowBlur: 5,
                        color: '#ADE7BC',
                    }
                },
                // 通用边样式
                lineStyle: {
                    normal: {
                        // 透明度，1为不透明
                        opacity: 1,
                        // 曲度，0为直线
                        curveness: 0
                    }
                },
                // 节点数据
                nodes: [],
                // 边数据
                links: []
            }
        ]
    };
    myChart.setOption(option);
}


// 重新加载图谱
function reloadGraph(events, relations) {
    // 清除原来的事件和关系
    EVENT_DICT = {};
    RELATION_DICT = {};

    events.forEach(function (event) {
        EVENT_DICT[event['code']] = event;
    });

    relations.forEach(function (relation) {
        RELATION_DICT[relation['code']] = relation;
    });

    var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
    var nodes = result[0];
    var links = result[1];
    var option = myChart.getOption();
    option.series[0].nodes = nodes;
    option.series[0].links = links;
    myChart.setOption(option);
}


// 将数据拓展到图谱
function expandGraph(expandedEventCode, events, relations) {
    var isExpanded = false;

    events.forEach(function (event) {
        if (!(event['code'] in EVENT_DICT)) {
            EVENT_DICT[event['code']] = event;
            isExpanded = true;
        }
    });

    relations.forEach(function (relation) {
        if (!(relation['code'] in RELATION_DICT)) {
            RELATION_DICT[relation['code']] = relation;
            isExpanded = true;
        }
    });

    // 为被拓展的节点加高亮
    EVENT_DICT[expandedEventCode]['category'] = 'highlight';

    var result = buildNodesAndLinks(EVENT_DICT, RELATION_DICT);
    var nodes = result[0];
    var links = result[1];

    var option = myChart.getOption();
    option.series[0].nodes = nodes;
    option.series[0].links = links;
    myChart.setOption(option);

    if (!isExpanded) {
        toastr.warning('不能继续拓展');
    }
}


// 使用ajax查询数据
function ajaxQuery(data, success, error) {
    $.ajax({
        type: 'GET',
        url: '/api/query_abstract_event',
        data: data,
        dataType: 'json',
        success: success,
        error: error
    })
}


$(function () {
    // 初始化图谱
    initGraph();
    // 初始时隐藏右侧信息栏
    if ($('#cause').text().trim() === '') {
        $('#causal-info').hide();
        // $('#main').css('margin-right', '0')
    }
    // 获取数据
    ajaxQuery(
        { text: '军事行动轨迹图谱', layers: 1 },
        // 成功
        function (result) {
            reloadGraph(result['events'], result['relations']);
        },
        // 失败
        function () {
            toastr.error('加载图谱数据失败');
        }
    );

    // 双击事件拓展图谱
    myChart.on('dblclick', function (param) {
        if (param.dataType === 'node') {
            var node = param.data;
            // 只拓展抽象事件
            if (node.category === 'abstract') {
                ajaxQuery(
                    { text: node.value, layers: 1 },
                    // 成功
                    function (result) {
                        expandGraph(node.name, result['events'], result['relations']);
                    },
                    // 失败
                    function () {
                        expandGraph(node.name, [], []);
                    }
                );
            }
        }
    });

    // 鼠标放到因果边上时显示上下文
    myChart.on('mouseover', function (param) {
        if (param.dataType === 'edge') {
            var link = param.data;
            if (link.category === 'abstract_cause_effect') {
                var cause = link.exampleCause || "";
                var effect = link.exampleEffect || "";
                var condition = link.exampleCondition || "";
                var composition = link.exampleComposition || "";
                var concurrent = link.exampleConcurrent || "";
                var shortContext = link.exampleShortContext || "";
                var longContext = link.exampleLongContext || "";

                var richCause = '<span class="cause">' + cause + '</span>';
                var richEffect = '<span class="effect">' + effect + '</span>';
                var richCondition = '<span class="effect">' + condition + '</span>';
                var richComposition = '<span class="effect">' + composition + '</span>';
                var richConcurrent = '<span class="effect">' + concurrent + '</span>';

                var richShortContext = shortContext;
                richShortContext = richShortContext.replace(cause, richCause);
                richShortContext = richShortContext.replace(effect, richEffect);
                var richLongContext = longContext.replace(shortContext, richShortContext);

                $('#cause').html(richCause);
                $('#effect').html(richEffect);
                $('#condition').html(richCondition);
                $('#composition').html(richComposition);
                $('#concurrent').html(richConcurrent);
                $('#context').html(richLongContext);
                $('#causal-info').show()
                !cause ? ($('#cause').parent().hide()) : ($('#cause').parent().show())
                !effect ? ($('#effect').parent().hide()) : ($('#effect').parent().show())
                !condition ? ($('#condition').parent().hide()) : ($('#condition').parent().show())
                !composition ? ($('#composition').parent().hide()) : ($('#composition').parent().show())
                !concurrent ? ($('#concurrent').parent().hide()) : ($('#concurrent').parent().show())
                !context ? ($('#context').parent().hide()) : ($('#context').parent().show())
            }
        }
    });

    // 提交查询
    $('.search-box').submit(function (e) {
        // 阻止默认提交行为
        e.preventDefault();
        // 使用ajax提交
        ajaxQuery(
            { text: $('#search-text').val(), layers: 1 },
            // 成功
            function (result) {
                toastr.success('查询成功');
                reloadGraph(result['events'], result['relations'])
            },
            // 失败
            function () {
                toastr.warning('未查询到相关数据');
            }
        );
    });

    // 点击推荐查询
    $('.recommend-search').click(function (e) {
        e.preventDefault();
        $('#search-text').val($(this).text());
        $('.search-box').submit();
    });

    // 窗口大小改变时，重新调整图谱大小
    $(window).resize(function () {
        myChart.resize();
    });

});
